package com.jia.lidao.network.http;

import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.handmark.pulltorefresh.library.tools.NetUtil;
import com.jia.lidao.R;
import com.jia.lidao.RunningContext;
import com.jia.lidao.UserUtils;
import com.jia.lidao.enity.AgentRespDTO;
import com.jia.lidao.enity.DriverRespDTO;
import com.jia.lidao.enity.LoginRespDTO;
import com.jia.lidao.enity.Message;
import com.jia.lidao.enity.MessagetBeen;
import com.jia.lidao.enity.OrderLoanRespDTO;
import com.jia.lidao.enity.OrderlistRespDTO;
import com.jia.lidao.enity.PayResponseDTO;
import com.jia.lidao.enity.RemittanceRespDTO;
import com.jia.lidao.enity.User;
import com.jia.lidao.network.http.request.AbstractRequest;
import com.jia.lidao.network.http.request.impl.AdminRequest;
import com.jia.lidao.network.http.request.impl.DealAuditOrderRequest;
import com.jia.lidao.network.http.request.impl.DealWithLoanRequest;
import com.jia.lidao.network.http.request.impl.DealWithOrderRequest;
import com.jia.lidao.network.http.request.impl.DeliveryRequest;
import com.jia.lidao.network.http.request.impl.ForgetPswRequest;
import com.jia.lidao.network.http.request.impl.ForgetPswSmsRequest;
import com.jia.lidao.network.http.request.impl.GetDriversRequest;
import com.jia.lidao.network.http.request.impl.GetOrderAuditRequest;
import com.jia.lidao.network.http.request.impl.JpushBindRequest;
import com.jia.lidao.network.http.request.impl.LoanDetailRequest;
import com.jia.lidao.network.http.request.impl.LoginRequest;
import com.jia.lidao.network.http.request.impl.LogoutRequest;
import com.jia.lidao.network.http.request.impl.MessageCategoryRequest;
import com.jia.lidao.network.http.request.impl.MessagesRequest;
import com.jia.lidao.network.http.request.impl.ModifyLocationRequest;
import com.jia.lidao.network.http.request.impl.OrderDetailRequest;
import com.jia.lidao.network.http.request.impl.OrderListRequest;
import com.jia.lidao.network.http.request.impl.PasswordRequest;
import com.jia.lidao.network.http.request.impl.PayRequest;
import com.jia.lidao.network.http.request.impl.ReceptConfirmRequest;
import com.jia.lidao.network.http.request.impl.RefreshTokenRequest;
import com.jia.lidao.network.http.request.impl.RegisterRequest;
import com.jia.lidao.network.http.request.impl.RegisterSmsRequest;
import com.jia.lidao.network.http.request.impl.RemindDeliveryRequest;
import com.jia.lidao.network.http.request.impl.RemindPayRequest;
import com.jia.lidao.network.http.request.impl.RemindReceptRequest;
import com.jia.lidao.network.http.request.impl.SetMessageReadRequest;
import com.jia.lidao.others.enity.OrderInfor;
import com.jia.lidao.utils.LogUtil;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.HttpHandler;
import com.lidroid.xutils.http.RequestParams;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import java.net.ConnectException;
import java.net.SocketException;
import java.net.SocketTimeoutException;

/**
 * 业务请求类
 */
public class BusinessManager implements ResultCode {
    /**
     * 超时时间
     */
    private static final int TIMEOUT = 18000;

    public static final int TOKENTIMEOUT=10003;

    public static final String KEY_CODE = "err_code";

    public static final String KEY_MSG = "err_msg";

    // public static final String KEY_DATA = "data";

    private static BusinessManager instance;

    private Context mContext;

    private HttpUtils mHttpUtils;

    private BusinessManager() {
        // 超时时间设置为30秒
        this.mHttpUtils = new HttpUtils(TIMEOUT);
        // 关闭缓存功能
        mHttpUtils.configCurrentHttpCacheExpiry(0 * 1000);
        mHttpUtils.configDefaultHttpCacheExpiry(0);
    }

    /**
     * 获取业务请求管理对象
     */
    public static BusinessManager getInstance() {
        if (instance == null) {
            synchronized (BusinessManager.class) {
                if (instance == null) {
                    instance = new BusinessManager();
                }
            }
        }
        return instance;
    }

    /**
     * context初始化，用applicationcontext比较好
     *
     * @param context
     */
    public void init(Context context) {
        mContext = context;
    }

    /**
     * 执行具体的网络请求及响应解析
     *
     * @param request
     * @param callback
     * @return
     */
    private <DataType> HttpHandler sendRequest(final AbstractRequest request,
                                               final MyCallback<DataType> callback) {
        // 检查网络是否可用
        if (!NetUtil.isNetworkAvailable(mContext)) {
            requestErrorCallback(CODE_ERROR_NET_INVALID,
                    mContext.getString(R.string.network_invalide), callback);
            return null;
        }

        // 初始化请求参数
        if (UserUtils.getInstance().getAuthor()!= null
                && !TextUtils.isEmpty(UserUtils.getInstance().getAuthor().access_token)&&!(request instanceof RefreshTokenRequest)) {
            request.addParam("access_token",
                    UserUtils.getInstance().getAuthor().access_token);
        }
        request.initRequestParams();
        RequestParams params = request.getAddedParams();
        if (request.getHeaders() != null) {
            params.addHeaders(request.getHeaders());
        }
        LogUtil.log("Request",
                "request url = " + getRequestUrl(request.getUrl()), "i");
        trackRequestParams(params);
        return mHttpUtils.configTimeout(TIMEOUT).send(
                request.getRequestMethod(), getRequestUrl(request.getUrl()),
                params, new RequestCallBack<String>() {
                    @Override
                    public void onFailure(HttpException error, String arg1) {
                        if (error != null) {
                            error.printStackTrace();
                        }
                        // 封装网络层面的错误，向上层提供较友好的消息提示
                        String errorCode = CODE_ERROR_DEFAULT;
                        String errorMessage = mContext
                                .getString(R.string.network_error_common);
                        if (error != null && (error
                                .getCause() instanceof ConnectException
                                || error.getCause() instanceof SocketException
                                || error.getCause() instanceof NoHttpResponseException)) {
                            errorCode = CODE_ERROR_NET_INVALID;
                            errorMessage = mContext
                                    .getString(R.string.network_error);
                        } else if (error != null && (error
                                .getCause() instanceof SocketTimeoutException
                                || error.getCause() instanceof ConnectTimeoutException)) {
                            errorCode = CODE_ERROR_NET_INVALID;
                            errorMessage = mContext
                                    .getString(R.string.network_timeout);
                        }
                        requestErrorCallback(errorCode, errorMessage, callback);
                    }

                    @Override
                    public void onSuccess(ResponseInfo<String> arg0) {
                        if (arg0 == null || arg0.result == null) {
                            String errorMessage = mContext
                                    .getString(R.string.unknown_error);
                            requestErrorCallback(ResultCode.CODE_ERROR_FORMAT,
                                    errorMessage, callback);
                            return;
                        }
                        LogUtil.log("response", "response:" + arg0.result, "i");
                        try {
                            JSONObject response = new JSONObject(arg0.result);
                            // 如果需要自己解析（不走通用解析逻辑）
                            if (request.parseResultMyself()) {
                                request.parseResult(response, callback);
                                return;
                            }
                            requestSuccessCallback(request, callback, response);
                        } catch (JSONException e) {
                            e.printStackTrace();
                            String errorMessage = mContext.getString(
                                    R.string.network_error_format_error);
                            requestErrorCallback(ResultCode.CODE_ERROR_FORMAT,
                                    errorMessage, callback);
                        }
                    }

                    @Override
                    public void onLoading(long total, long current,
                                          boolean isUploading) {
                        super.onLoading(total, current, isUploading);
                    }

                    @Override
                    public void onCancelled() {
                        super.onCancelled();
                        if (callback != null) {
                            callback.onCancel();
                        }
                    }

                    @Override
                    public void onStart() {
                        super.onStart();
                        if (callback != null) {
                            callback.onStart();
                        }
                    }

                });
    }

    /**
     * 这边需要对请求url做统一处理，如加入authtoken
     *
     * @param url
     * @return
     */
    private String getRequestUrl(String url) {
        // if (TextUtils.isEmpty(Config.authtoken))
        // {
        // return url;
        // }
        // return url + "?authtoken=" + Config.authtoken;
        return url;
    }

    /**
     * 打印请求参数
     *
     * @param params
     */
    private void trackRequestParams(RequestParams params) {
        if (params != null && params.getQueryStringParams() != null) {
            for (NameValuePair np : params.getQueryStringParams()) {
                LogUtil.log("Request", String.format("param [%s]=[%s]",
                        np.getName(), np.getValue()), "i");
            }
        }
        if (params != null) {
            HttpEntity en = params.getEntity();
            if (en != null) {
                try {
                    String p = EntityUtils.toString(en);
                    LogUtil.log("Request", "body params = " + p, "i");
                } catch (Exception e) {
                    LogUtil.log("Request", "print body params error", "i");
                }

            }
        }

    }

    /**
     * 请求成功后的数据解析，此方法仅仅是网络请求成功后回调，网络请求成功并不代表业务接口调用成功
     *
     * @param request
     * @param callback
     * @param response
     */
    @SuppressWarnings("unchecked")
    private <DataType> void requestSuccessCallback(
            final AbstractRequest request, final MyCallback<DataType> callback,
            final JSONObject response) {
        String resultCode = response.optString(KEY_CODE);
        // 业务处理成功
        // 接口返回数据格式比对
        if (CODE_SUCCESS.equals(resultCode)) {
            String resultData = response.toString();
            // String resultData = response.optString(KEY_DATA);
            String message = response.optString(KEY_MSG);
            Gson resultGson = new Gson();
            try {
                if (request.getResultType() != null
                        && request.getResultType() != Void.class) {
                    // added by czhang， String解析单独拎出来
                    // resultGson.fromJson()解析的字符串中有空格时解析抛出异常，特修改 20151217 商好值
                    if (request.getResultType() == String.class) {
                        callback.onSuccess((DataType) resultData, message);
                        callback.onFinished();
                        return;
                    }
                    DataType resultObj = (DataType) resultGson
                            .fromJson(resultData, request.getResultType());
                    if (resultObj == null)// result必须非空
                    {
                        String errorMessage = mContext
                                .getString(R.string.unknown_error);
                        requestErrorCallback(ResultCode.CODE_ERROR_FORMAT,
                                errorMessage, callback);
                    } else {
                        callback.onSuccess(resultObj, message);
                    }
                } else {
                    callback.onSuccess(null, message);
                }
            } catch (Exception e) {
                e.printStackTrace();
                // 数据解析失败
                String errorMessage = mContext
                        .getString(R.string.unknown_error);
                requestErrorCallback(ResultCode.CODE_ERROR_FORMAT, errorMessage,
                        callback);
            }
            callback.onFinished();
        }
        // 业务处理失败，resultCode为1
        else {
            String message = response.optString(KEY_MSG);
            final String errorCode = response.optString(KEY_CODE);
            if(errorCode.equals(TOKENTIMEOUT+"")){
                callback.onError(errorCode,"");
                callback.onFinished();
                callback.onRefreshToken();
                return;
            }
            callback.onError(errorCode, message);
            callback.onFinished();
        }
    }

    private <DataType> void requestErrorCallback(String errorCode,
                                                 String message, final MyCallback<DataType> callback) {
        callback.onError(errorCode, message);
        callback.onFinished();
    }

    // ********************************************业务请求***************************************

    /**
     * 登录
     */
    public void loginTel(LoginRequest request,
                         MyCallback<LoginRespDTO> callback) {
        sendRequest(request, callback);
    }


    /**
     * 个人中心信息拉取
     *
     * @param request
     * @param callback
     */
    public void getAgent(AdminRequest request, MyCallback<AgentRespDTO> callback) {
        sendRequest(request, callback);
    }


    /**
     * 获取订单列表
     *
     * @param request
     * @param callback
     */
    public void getOrderList(OrderListRequest request, MyCallback<OrderlistRespDTO> callback) {
        sendRequest(request, callback);
    }

    /**
     * 发送注册验证码
     */
    public void sendRegisterSms(RegisterSmsRequest request, MyCallback<Void> callback) {
        sendRequest(request, callback);
    }

    /**
     * 发送忘记密码的验证码
     */
    public void sendForgetSms(ForgetPswSmsRequest request, MyCallback<Void> callback) {
        sendRequest(request, callback);
    }

    /**
     * 忘记密码验证
     */
    public void sendForgetVerify(ForgetPswRequest request, MyCallback<Void> callback) {
        sendRequest(request, callback);
    }

    /**
     * 登录验证
     */
    public void sendRegisterVerify(RegisterRequest request, MyCallback<Void> callback) {
        sendRequest(request, callback);
    }

    /**
     * 登出
     */
    public void logout(LogoutRequest request, MyCallback<Void> callback) {
        sendRequest(request, callback);
    }

    /**
     * 修改密码
     */
    public void changePassword(PasswordRequest request,
                               MyCallback<Void> callback) {
        sendRequest(request, callback);
    }

    /**
     * 提醒发货
     */
    public void remindDeliver(RemindDeliveryRequest request,MyCallback<Void> callback){
        sendRequest(request,callback);
    }

    /**
     * 提醒付款
     */
    public void remindPay(RemindPayRequest request,MyCallback<Void> callback){
        sendRequest(request,callback);
    }

    /**
     * 提醒收货
     */
    public void remindRecept(RemindReceptRequest request,MyCallback<Void> callback){
        sendRequest(request,callback);
    }


    /**
     * 确认收货
     */
    public void confirmRecept(ReceptConfirmRequest request,MyCallback<Void> callback){
        sendRequest(request,callback);
    }


    /**
     * 获取订单详情
     */
    public void getOrderDetail(OrderDetailRequest request, MyCallback<OrderInfor> callback){
        sendRequest(request,callback);
    }


    /**
     * 查询消息分类
     */
    public void getMessageCategory(MessageCategoryRequest request,
                                   MyCallback<Message> callback) {
        sendRequest(request, callback);
    }

    /**
     * 查询消息列表
     */
    public void getMessages(MessagesRequest request,
                            MyCallback<MessagetBeen> callback) {
        sendRequest(request, callback);

    }

    /**
     * 发货
     */
    public void delivery(DeliveryRequest request,MyCallback<Void> callback){
        sendRequest(request,callback);
    }

    /**
     * 拉取司机信息
     */
    public void getDrivers(GetDriversRequest request, MyCallback<DriverRespDTO> callback){
        sendRequest(request,callback);
    }

    /**
     * 绑定jpush
     * jpush_import
     */
    public void bindJpush(JpushBindRequest request, MyCallback<Void> callback) {
        sendRequest(request, callback);
    }

    /**
     * 处理订单统一接口
     * @param request
     * @param callback
     */
    public void dealWithOrder(DealWithOrderRequest request,MyCallback<Void> callback){
        sendRequest(request,callback);
    }


    /**
     * 获取订货审核信息
     * @param request
     * @param callback
     */
    public void getOrderAuditInfo(GetOrderAuditRequest request,MyCallback<RemittanceRespDTO> callback){
        sendRequest(request,callback);
    }


    /**
     * 获取农资贷审核信息
     * @param request
     * @param callback
     */
    public void getLoanDetailInfo(LoanDetailRequest request,MyCallback<OrderLoanRespDTO> callback){
        sendRequest(request,callback);
    }

    /**
     * 审核订货
     * @param request
     * @param callback
     */
    public void dealWithOrderAudit(DealAuditOrderRequest request, MyCallback<Void> callback){
        sendRequest(request,callback);
    }

    /**
     * 审核农资贷
     * @param request
     * @param callback
     */
    public void dealWithLoanAudit(DealWithLoanRequest request,MyCallback<Void> callback){
        sendRequest(request,callback);
    }

    /**
     * 付款
     * @param request
     * @param callback
     */
    public void payOrder(PayRequest request,MyCallback<PayResponseDTO> callback){
        sendRequest(request,callback);
    }


    /**
     * 置换凭证
     * @param request
     * @param callback
     */
    public void refreshToken(RefreshTokenRequest request,MyCallback<LoginRespDTO> callback){
        sendRequest(request,callback);
    }


    /**
     * 更新消息为已读
     */
    public void setMessageRead(SetMessageReadRequest request,MyCallback<Void> callback){
        sendRequest(request,callback);
    }


    /**
     * 更新店铺地址
     * @param request
     * @param callback
     */
    public void changeLocation(ModifyLocationRequest request,MyCallback<Void> callback){
        sendRequest(request,callback);
    }



}

